package com.bkgy.controller.planking.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bkgy.controller.planking.dao.PlanKing1870Dao;
import com.bkgy.controller.planking.dao.TBProfit1870Dao;
import com.bkgy.controller.planking.dao.TBProfit1870ResDao;
import com.bkgy.controller.planking.entity.*;
import com.bkgy.controller.planking.service.IProfit1870JobService;
import com.bkgy.controller.planking.service.PlanKing1870Service;
import com.bkgy.controller.planking.util.ProfitUtil;
import com.bkgy.controller.technology.entity.TDefectData;
import com.bkgy.controller.technology.service.ITDefectDataService;
import com.bkgy.util.DateUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Slf4j
@RequiredArgsConstructor
@Service
public class Profit1870ServiceImpl implements IProfit1870JobService {
    private final PlanKing1870Service baseService;
    private final ITDefectDataService defectService;
    private final PlanKing1870Dao dao;
    private final TBProfit1870Dao profitDao;
    private final TBProfit1870ResDao profitResDao;

    @Override
    public void profit1870Job() {
        String timeLevel = getStart();

        List<TbProfit1870Par> list = dao.loadBaseDate(timeLevel, null);
        log.info("识别新卷{}", list.size());

        //更新缺陷等级数据（注意，缺陷表里有重复数据）
        Date d = DateUtil.getStringToDate("yyyyMMddHHmmss", timeLevel);
        LambdaQueryWrapper<TDefectData> w = new LambdaQueryWrapper();
        Map<String, String> defectMap = new HashMap<>();
        w.ge(TDefectData::getCreateTime, d).orderByAsc(TDefectData::getCreateTime);
        List<TDefectData> defectList = defectService.list(w);
        for (TDefectData defectData : defectList) {
            defectMap.put(defectData.getExtId(), defectData.getDefectClass1());
        }
        for (TbProfit1870Par par : list) {
            for (TbProfit1870Sub sub : par.getSubList()) {
                if (defectMap.containsKey(sub.getExtid())) {
                    sub.setDefectLevel(defectMap.get(sub.getExtid()));
                }
            }
        }
        //识别新数据异常情况保存
        baseService.dealData(list, timeLevel);
    }

    //构建一个删除的时间点
    private String getStart() {
//        Calendar cal = Calendar.getInstance();
//        cal.setTime(new Date());
//        int hour = cal.get(Calendar.HOUR_OF_DAY);
//        String timeLevel = "";
//        if (hour >= 8 && hour < 19) {
//            timeLevel = DateUtil.getDateToString(new Date(), "yyyyMMdd073000");
//        } else {
//            timeLevel = DateUtil.getDateToString(new Date(), "yyyyMMdd183000");
//        }
//
//        return timeLevel;

        //清除XX时间内的数据，重新生成，解决班组、异常指标滞后问题
        int hour = -1;//删除1小时内数据
        Calendar cal = Calendar.getInstance();
        TbProfit1870 p = profitDao.selectTopRecord(null);
        log.info("最新记录时间:{}", p.getCredate());
        if (p != null) cal.setTime(DateUtil.getStringToDate("yyyyMMddHHmmss", p.getCredate()));
        cal.add(Calendar.HOUR, hour);
        String timeLevel = DateUtil.getDateToString(cal.getTime(), "yyyyMMddHHmmss");
        //查询此时间后的入口卷号，进而获得最早一个出口卷，删除此出口卷时间后的记录
        p = profitDao.selectTopTimeEntIdRecord(timeLevel);
        log.info("临界时间入口卷号：{}", p.getEntid());
        if (p != null) {
            p = profitDao.selectTopTimeExtIdRecord(p.getEntid());
            timeLevel = p.getCredate();
            log.info("临界时间第一卷出口卷号：{}，时间：{}", p.getExtid(), timeLevel);
        }
        return timeLevel;
    }

    @Override
    public void profit1870ResJob(Date today) {
        //累计小时数，白班11小时，夜班13小时
        int hourLevel = isDay(today);
        BigDecimal sumHour = BigDecimal.ZERO;
        BigDecimal sumActOutput = BigDecimal.ZERO;
        //平均入口机时产量
        BigDecimal inputHourAvg = BigDecimal.ZERO;
        //平均吨钢收益
        BigDecimal tonProfitAvg = BigDecimal.ZERO;
        //收益
        BigDecimal sumProfit = BigDecimal.ZERO;

        //从T_PDI_DATA_L3_CGL1870_SEQ 和 T_PDI_DATA_L3_CGL1870中加载PROCESSFLAG=0|9 当日数据
        List<TbProfit1870Step1> baseList = dao.loadStep1(DateUtil.getCurrentZero(today), DateUtil.getNextDayZero(today));
        log.info("加载{}条数据\n", baseList.size());

        for (int i = 0; i < baseList.size(); i++) {
            TbProfit1870Step1 step = baseList.get(i);
            //初始化数据标准
            BigDecimal outputWidth = step.getOutMatWidth().multiply(BigDecimal.TEN);//乘10
            BigDecimal outputThick = step.getOutMatThick().multiply(BigDecimal.valueOf(1000));//乘1000
            log.info("当前使用的记录入口卷号： {} ,出口宽度 {} ,出口厚度 {} ", step.getEntid(), step.getOutMatWidth(), step.getOutMatThick());

            List<TbProfit1870> proList = new ArrayList<>();
//            //宽度浮动，±100mm，为了统一单位×10
//            BigDecimal w1 = outputWidth.subtract(BigDecimal.valueOf(1000));
//            BigDecimal w2 = outputWidth.add(BigDecimal.valueOf(1000));
//            //厚度浮动，±0.1，为了统一单位×1000
//            BigDecimal t1 = outputThick.subtract(BigDecimal.valueOf(100));
//            BigDecimal t2 = outputThick.add(BigDecimal.valueOf(100));
            Integer widthClass = ProfitUtil.getWidthGrade(outputWidth);
            Integer thickClass = ProfitUtil.getThickGrade(outputThick);
            proList = profitDao.listProfit1(step.getSteelgrade(), widthClass, thickClass);
            if (proList.size() == 0) {
                log.info("按钢种查询，钢种：{}", step.getSteelgrade());
                profitDao.listProfit2(step.getSteelgrade());
            }
            if (proList.size() == 0) {
                log.info("按宽度等级和厚度等级查询，宽度等级：{}，厚度等级：{}", widthClass, thickClass);
                profitDao.listProfit3(widthClass, thickClass);
            }

            if (!proList.isEmpty()) {
                //平均成材率
                BigDecimal yeildAvg = BigDecimal.ZERO;

                //求入口机时、成材率、吨钢收益的平均值
                for (TbProfit1870 pro : proList) {
                    inputHourAvg = inputHourAvg.add(pro.getInputHour());
                    yeildAvg = yeildAvg.add(pro.getYeild());
                    tonProfitAvg = tonProfitAvg.add(pro.getTonProfit());
                }
                inputHourAvg = inputHourAvg.divide(BigDecimal.valueOf(proList.size()), 4, BigDecimal.ROUND_HALF_UP);
                yeildAvg = yeildAvg.divide(BigDecimal.valueOf(proList.size()), 4, BigDecimal.ROUND_HALF_UP);
                tonProfitAvg = tonProfitAvg.divide(BigDecimal.valueOf(proList.size()), 4, BigDecimal.ROUND_HALF_UP);

                log.info("当前累计第{}条记录，使用的入口卷号是： {} ", i, step.getEntid());
                //卷预计生产时间
                BigDecimal bar = step.getInMatWt().divide(inputHourAvg, 4, BigDecimal.ROUND_HALF_UP);
                log.info("当前累加时间 {} ，参考卷预计生产时间：【{}】\n", sumHour, bar);
                //累计时间达到
                if (sumHour.add(bar).compareTo(BigDecimal.valueOf(hourLevel)) > 0) break;
                sumHour = sumHour.add(bar);
                BigDecimal outMt = step.getInMatWt().multiply(yeildAvg);
                //累加效益
                sumProfit = sumProfit.add(outMt.multiply(tonProfitAvg));

                sumActOutput = sumActOutput.add(outMt);
            } else {
                log.warn("【 {} 】查询不到数据", step.getEntid());
            }
        }

        //tb_profit1870查不到对应记录 inputHourAvg|tonProfitAvg 为0，查询近30的机时|效益平均值
        if (inputHourAvg.compareTo(BigDecimal.ZERO) == 0) {
            List<TbProfit1870> list = profitDao.selectNumRecord(30);
            for (TbProfit1870 pro : list) {
                inputHourAvg = inputHourAvg.add(pro.getInputHour());
                tonProfitAvg = tonProfitAvg.add(pro.getTonProfit());
            }
            inputHourAvg = inputHourAvg.divide(BigDecimal.valueOf(list.size()), 4, BigDecimal.ROUND_HALF_UP);
            tonProfitAvg = tonProfitAvg.divide(BigDecimal.valueOf(list.size()), 4, BigDecimal.ROUND_HALF_UP);
        }

        //补出不满时间对应的重量：(不足时间×平均入口产量)+累加产量
        BigDecimal otherWt = BigDecimal.valueOf(hourLevel).subtract(sumHour).multiply(inputHourAvg);
        sumActOutput = otherWt.add(sumActOutput);
        sumProfit = otherWt.multiply(tonProfitAvg).add(sumProfit).divide(BigDecimal.valueOf(10000), 4, BigDecimal.ROUND_HALF_UP);

        String timePoint = DateUtil.getDateToString(today, "yyyyMMddHH");
        profitResDao.deleteById(timePoint);
        profitResDao.insert(new TbProfit1870Res(timePoint, BigDecimal.valueOf(hourLevel), sumActOutput, sumProfit));
    }

    /**
     * 识别白班、夜班
     */
    private int isDay(Date today) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(today);
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        //8点--19点为白班
        int h = (hour >= 8 && hour < 19) ? 11 : 13;
        log.info("当前时间：{}，班小时数：{}", DateUtil.getDateToString(today, "yyyy-MM-dd HH:mm:ss"), h);
        return h;
    }
}
